/*
 * @lc app=leetcode.cn id=3 lang=javascript
 *
 * [3] 无重复字符的最长子串
 */

// @lc code=start
/**
 * 给定一个字符串 s ，请你找出其中不含有重复字符的 最长子串 的长度。
 * 
  示例 1:
  输入: s = "abcabcbb"
  输出: 3 
  解释: 因为无重复字符的最长子串是 "abc"，所以其长度为 3。

  示例 2:
  输入: s = "bbbbb"
  输出: 1
  解释: 因为无重复字符的最长子串是 "b"，所以其长度为 1。

  示例 3:
  输入: s = "pwwkew"
  输出: 3
  解释: 因为无重复字符的最长子串是 "wke"，所以其长度为 3。
      请注意，你的答案必须是 子串 的长度，"pwke" 是一个子序列，不是子串。

  提示：
  0 <= s.length <= 5 * 104
  s 由英文字母、数字、符号和空格组成
  (A)AB -> (A)AB
  A(A)B -> A(AB)
  AA(B) -> AA(B)
 * @param {string} str 给定统计得字符串
 * @return {number}
 */
let inTest = arguments[arguments.length-1].includes('gitee')
var lengthOfLongestSubstring = function(s) {
  //字符串的长度
  let l = s.length;
  //滑动窗口
  let slidingWindow = [];
  //最长不不重复字符串的长度
  let ans = 0;
  //保存内存循环位置，就是滑动窗口最后一个字符在s中的位置
  let k = 1;
  for (let i = 0; i < l; i++) {
    if(i==0) {
      const char = s.charAt(i);
      slidingWindow.push(char);
    }else {
      //滑动窗口删除第一个元素，代替s中取一个元素添加到滑动窗口中，节省性能
      slidingWindow.shift();
    }

    //获取最长不重复字符串
    for(; k < l; k++) {
      const char1 = s.charAt(k);
      //当有重复时终止循环
      if(slidingWindow.includes(char1)) {
        break;
      }else{
        slidingWindow.push(char1);
      }
    }
    if(inTest) {
      console.log("array",slidingWindow,"length:",slidingWindow.length);
    }
    //记录最长不重复字符串的长度
    ans = Math.max(ans,slidingWindow.length);
    //如果内存循环遍历完一次，就已经求出最长字符串了
    if(k==l) {
      break;
    }
  }
  return ans;
}

/**
 * 基本测试通过，性能不好，通过读取评论才知道是滑动窗口问题
 * 使用队列解决
 * @param {*} str 
 * @returns 
 */
var lengthOfLongestSubstringTest = function(str) {
  let longestSubStr = "";
  let result = "";
  for(let i=0;i<str.length;i++) {
    let subStr = longestSubStr;
    let char = str.charAt(i);
    let reset = subStr.includes(char);
    if(reset) {
      //1.第一个字符重复，删除第一个字符
      //2.最后一个字符重复，重置
      //3.中间重复，截取1
      longestSubStr = "";
      if(subStr.startsWith(char)) {
        subStr = subStr.substring(1)+char;
      }else if(subStr.endsWith(char)) {
        subStr = char;
      }else {
        subStr = subStr.substring(subStr.indexOf(char)+1)+char;
      }
    }else{
      subStr += char;
    }
    //判断字符串是否重复
    if(str.split(subStr).length >= 1) {
      if(subStr.length > longestSubStr.length) {
        longestSubStr = subStr;
        if(longestSubStr.length > result.length) {
          result = longestSubStr;
        }
      }
    }
    if(inTest) {
      console.log("subStr:",subStr,"longestSubStr:",longestSubStr,"result",result)
    }
  }
  return result.length;
}
;
[
  {
    "test":"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!\"#$%&'(",
    "expected":70
  },
  {
    "test":"nfpdmpi",//ip  mdpfn
    "expected":5
  },
  {
    "test":"dvdf",//
    "expected":3
  },
  {
    "test":"abcabcbb",
    "expected":3
  },
  {
    "test":"bbbbbbb",
    "expected":1
  },
  {
    "test":"pwwkew",
    "expected":3
  },
  {
    "test":"aab",
    "expected":2
  },
  {
    "test":"anviaj",
    "expected":5
  }
].forEach(e=>{
  if(inTest) {
    console.log(e.test,e.expected,lengthOfLongestSubstring(e.test))
  }
})
// @lc code=end
  
  